﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WatiNCF.Steps;

namespace WatiNCF
{
    public class WizardPageController<TInterface> : PageController<TInterface>, IWizardPageController<TInterface> 
        where TInterface : class
    {
        public event EventHandler<StepEventArgs> BeforeStepNext;
        public event EventHandler<StepEventArgs> AfterStepNext;
        public event EventHandler<StepEventArgs> BeforeStepPrevious;
        public event EventHandler<StepEventArgs> AfterStepPrevious;

        public IWizardController<TInterface> Wizard { get; set; }

        public WizardPageController(IHomePageController homePage, IPageController parentPage)
            : base(homePage, parentPage)
        {
            Wizard = new WizardController<TInterface>(this);
        }

        public void ExecuteStepNext(Action action)
        {
            if (!StopExecution)
            {
                StopExecution = FireBeforeStepNext(action.Method.Name);
                if (!StopExecution)
                {
                    base.ExecuteStep(action);
                    Wizard.StepNext(action.Method.Name);
                    if (!StopExecution)
                    {
                        StopExecution = FireAfterStepNext(action.Method.Name);
                    }
                }
            }
        }

        public void ExecuteStepPrevious(Action action)
        {
            if (!StopExecution)
            {
                StopExecution = FireBeforeStepPrevious(action.Method.Name);
                if (!StopExecution)
                {
                    base.ExecuteStep(action);
                    Wizard.StepPrevious(action.Method.Name);
                    if (!StopExecution)
                    {
                        StopExecution = FireAfterStepPrevious(action.Method.Name);
                    }
                }
            }
        }

        public override TInterface ResetExecutionFlag()
        {
            Wizard.ResetExecutionFlag();
            return base.ResetExecutionFlag();
        }

        private bool FireBeforeStepNext(string stepName)
        {
            StepEventArgs args = new StepEventArgs(stepName);
            if (BeforeStepNext != null)
            {
                BeforeStepNext(this, args);
            }
            return args.StopExecution;
        }

        private bool FireAfterStepNext(string stepName)
        {
            StepEventArgs args = new StepEventArgs(stepName);
            if (AfterStepNext != null)
            {
                AfterStepNext(this, args);
            }
            return args.StopExecution;
        }

        private bool FireBeforeStepPrevious(string stepName)
        {
            StepEventArgs args = new StepEventArgs(stepName);
            if (BeforeStepPrevious != null)
            {
                BeforeStepPrevious(this, args);
            }
            return args.StopExecution;
        }

        private bool FireAfterStepPrevious(string stepName)
        {
            StepEventArgs args = new StepEventArgs(stepName);
            if (BeforeStepPrevious != null)
            {
                BeforeStepPrevious(this, args);
            }
            return args.StopExecution;
        }

        /// <summary>
        /// Finishes execution of any further steps before the specified step has started.
        /// </summary>
        /// <param name="stepName">The name of the step to finish after.</param>
        public TInterface FinishBeforeStepNext(string stepName)
        {
            EnsureStepExists(stepName);
            Wizard.BeforeStepNext += (sender, args) =>
            {
                if (args.StepName == stepName)
                {
                    args.StopExecution = true;
                    StopExecution = true;
                }
            };
            return this as TInterface;
        }

        /// <summary>
        /// Finishes execution of any further steps after the specified step has completed.
        /// </summary>
        /// <param name="stepName">The name of the step to finish after.</param>
        /// <returns></returns>
        public TInterface FinishAfterStepNext(string stepName)
        {
            EnsureStepExists(stepName);
            Wizard.AfterStepNext += (sender, args) =>
            {
                if (args.StepName == stepName)
                {
                    args.StopExecution = true;
                    StopExecution = true;
                }
            };
            return this as TInterface;
        }
    }
}
